/************************************************************************/
// Copyright (C) 2016, han_gangbiao. All rights reserved.
// Use of this source code is governed by a GPL-v2 license that can be found in the License file.
// 
// [Time]:      2016-1-4 21:53:17
// [Author]:    han_gangbiao [http://my.oschina.net/jackhen]
// [Info]:      
/************************************************************************/

#ifndef INCLUDE_BASE_XREFPTR_H_
#define INCLUDE_BASE_XREFPTR_H_

#include "baseheader.h"
#include "xatomic.h"

BEG_NS_SMART

template<class T> class ref_ptr;
class refobj_t
{
public:
	inline long get_refcount() const { return m_ref.get(); }
protected:
	refobj_t() { }
	virtual ~refobj_t() { }
	virtual void destroy();
private:
	template<class T> friend class ref_ptr;
	long add_ref();
	long release();
private:
	atomic_t m_ref;
};

template<class T>
class ref_ptr
{
public:
	ref_ptr(T* p = NULL) : pRefObj_(p){ if(pRefObj_) pRefObj_->add_ref(); }
	ref_ptr(const ref_ptr<T>& rp) : pRefObj_(rp.pRefObj_){ if(pRefObj_) pRefObj_->add_ref(); }
    ~ref_ptr(){ if(pRefObj_) { pRefObj_->release(); pRefObj_ = NULL; } }

public:
    inline ref_ptr<T>& operator=(const ref_ptr<T>& rp)
    {
        if(pRefObj_ == rp.pRefObj_)
            return *this;

        if(pRefObj_) pRefObj_->release();

        pRefObj_ = rp.pRefObj_;
        if(pRefObj_) pRefObj_->add_ref();
        return *this;
    }

    inline ref_ptr<T>& operator=(T* p)
    {
        if(pRefObj_ == p)
            return *this;

        if(pRefObj_) pRefObj_->release();

        pRefObj_ = p;
        if(pRefObj_) pRefObj_->add_ref();
        return *this;
    }

    inline T* operator->() const { return pRefObj_; }
    inline T* getPointer() const { return pRefObj_; }

    inline bool operator==(const ref_ptr<T>& rp) const { return pRefObj_ == rp.pRefObj_; }
    inline bool operator==(const T* p) const { return pRefObj_ == p; }
    inline bool operator==(int p) const { return pRefObj_ == (T*)(intptr_t)p; } //> RefPointer == NULL //C++
    inline bool operator==(long p) const { return pRefObj_ == (T*)(intptr_t)p; } //> RefPointer == NULL //64 bits //C++
    inline bool operator==(void* p) const { return pRefObj_ == (T*)p; } //> RefPointer == NULL // C
    inline bool operator!=(const ref_ptr<T>& rp) const { return pRefObj_ != rp.pRefObj_; }
    inline bool operator!=(const T* p) const { return pRefObj_ != p; }
    inline bool operator!=(int p) const { return pRefObj_ != (T*)(intptr_t)p; } //> RefPointer != NULL //C++
    inline bool operator!=(long p) const { return pRefObj_ != (T*)(intptr_t)p; } //> RefPointer != NULL //64 bits //C++
    inline bool operator!=(void* p) const { return pRefObj_ != (T*)p; } //> RefPointer != NULL // C
    inline operator bool() const { return pRefObj_ != NULL; } //>mark: if(RefPointer)
    inline bool operator!() const { return pRefObj_ == NULL; }
    inline bool operator<(const ref_ptr<T>& rp) const { return pRefObj_ < rp.pRefObj_; }

protected:
    T* pRefObj_;

};

END_NS_SMART

#endif //~INCLUDE_BASE_XREFPTR_H_
